<template>
  <div class="face-capture">
    <div class="camera-container">
      <video
        ref="videoRef"
        :width="width"
        :height="height"
        autoplay
        muted
        playsinline
        v-show="showVideo"
      ></video>
      
      <canvas
        ref="canvasRef"
        :width="width"
        :height="height"
        v-show="!showVideo && capturedImage"
      ></canvas>
      
      <div v-if="!cameraReady && !capturedImage" class="loading">
        <el-icon class="is-loading"><Loading /></el-icon>
        <p>正在启动摄像头...</p>
      </div>
      
      <div v-if="error" class="error">
        <el-icon><Warning /></el-icon>
        <p>{{ error }}</p>
      </div>
    </div>
    
    <div class="controls">
      <el-button
        v-if="!capturedImage"
        type="primary"
        :disabled="!cameraReady"
        @click="capturePhoto"
        :loading="capturing"
      >
        <el-icon><Camera /></el-icon>
        拍照
      </el-button>
      
      <template v-else>
        <el-button @click="retakePhoto">
          <el-icon><RefreshLeft /></el-icon>
          重拍
        </el-button>
        <el-button type="primary" @click="confirmPhoto">
          <el-icon><Check /></el-icon>
          确认
        </el-button>
      </template>
    </div>
    
    <div v-if="tips" class="tips">
      <el-alert
        :title="tips"
        type="info"
        :closable="false"
        show-icon
      />
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Camera, RefreshLeft, Check, Loading, Warning } from '@element-plus/icons-vue'
import { getCameraPermission, stopCameraStream } from '@/utils/auth'

// Props
const props = defineProps({
  width: {
    type: Number,
    default: 640
  },
  height: {
    type: Number,
    default: 480
  },
  tips: {
    type: String,
    default: '请将人脸对准摄像头，确保光线充足'
  }
})

// Emits
const emit = defineEmits(['captured', 'error'])

// Refs
const videoRef = ref(null)
const canvasRef = ref(null)

// State
const cameraReady = ref(false)
const showVideo = ref(true)
const capturedImage = ref(null)
const capturing = ref(false)
const error = ref('')
const stream = ref(null)

// 初始化摄像头
const initCamera = async () => {
  try {
    error.value = ''
    stream.value = await getCameraPermission()
    
    if (videoRef.value) {
      videoRef.value.srcObject = stream.value
      videoRef.value.onloadedmetadata = () => {
        cameraReady.value = true
      }
    }
  } catch (err) {
    error.value = err.message || '无法访问摄像头'
    emit('error', error.value)
  }
}

// 拍照
const capturePhoto = () => {
  if (!cameraReady.value || capturing.value) return
  
  capturing.value = true
  
  try {
    const canvas = canvasRef.value
    const video = videoRef.value
    const ctx = canvas.getContext('2d')
    
    // 绘制视频帧到canvas
    ctx.drawImage(video, 0, 0, props.width, props.height)
    
    // 获取Base64数据
    const base64Data = canvas.toDataURL('image/jpeg', 0.8)
    capturedImage.value = base64Data
    showVideo.value = false
    
    ElMessage.success('拍照成功')
  } catch (err) {
    ElMessage.error('拍照失败: ' + err.message)
  } finally {
    capturing.value = false
  }
}

// 重新拍照
const retakePhoto = () => {
  capturedImage.value = null
  showVideo.value = true
}

// 确认照片
const confirmPhoto = () => {
  if (capturedImage.value) {
    emit('captured', capturedImage.value)
  }
}

// 停止摄像头
const stopCamera = () => {
  if (stream.value) {
    stopCameraStream(stream.value)
    stream.value = null
  }
  cameraReady.value = false
}

// 生命周期
onMounted(() => {
  initCamera()
})

onUnmounted(() => {
  stopCamera()
})

// 暴露方法
defineExpose({
  capturePhoto,
  retakePhoto,
  stopCamera,
  initCamera
})
</script>

<style scoped>
.face-capture {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.camera-container {
  position: relative;
  border: 2px solid #dcdfe6;
  border-radius: 8px;
  overflow: hidden;
  background: #f5f7fa;
}

.camera-container video,
.camera-container canvas {
  display: block;
  background: #000;
}

.loading,
.error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  color: #606266;
}

.error {
  color: #f56c6c;
}

.loading .el-icon,
.error .el-icon {
  font-size: 32px;
  margin-bottom: 10px;
}

.controls {
  display: flex;
  gap: 12px;
}

.tips {
  max-width: 400px;
}
</style>
